<?php

class HTML_Fluent_Serializer {

    public function serialize(HTML_Fluent_Element $element) {
        $o = '';
        $stack = array(array('n' => $element, 'i' => 0));

        while (!empty($stack)) {
            $node =& $stack[$this->end($stack)];
            if ($node['n'] instanceof HTML_Fluent_Text) {
                $o .= htmlspecialchars($node['n']);
                array_pop($stack);
                continue;
            }
            $childNodes = $node['n']->getChildNodes();
            if (empty($childNodes)) {
                array_pop($stack);
                $o .= sprintf('<%s%s />', $node['n']->getName(), $this->attr($node['n']));
                continue;
            }
            if ($node['i'] == 0) {
                $o .= sprintf('<%s%s>', $node['n']->getName(), $this->attr($node['n']));
            }
            $cur = $this->pos($childNodes, $node['i']);
            if (!$cur) {
                array_pop($stack);
                $o .=  '</'. $node['n']->getName() .'>';
                continue;
            }
            $node['i']++;
            $stack[] = array('n' => $cur, 'i' => 0);
        }
        return $o;
    }

    protected function pos($nodes, $pos) {
        $i = 0;
        foreach ($nodes as $node) {
            if ($i == $pos) {
                return $node;
            }
            $i++;
        }
        return null;
    }

    protected function end($stack) {
        $last = null;
        foreach ($stack as $key => $node) {
            $last = $key;
        }
        return $last;
    }

    protected function attr($element) {
        $list = array();
        foreach ($element->getAttributes() as $name => $value) {
            if ($value === null) continue;
            $list[] = sprintf('%s="%s"', $name, htmlspecialchars($value));
        }
        if (empty($list)) return '';
        return ' '. implode(' ', $list);
    }

}
